package com.googlecode.horncomb.core.paged;

import java.io.Serializable;
import java.util.List;

/**
 * 分页页面列表,数据源包括所有的数据记录.
 * @author Daniel
 */
public class PagedListImpl<Type extends List<?>> extends
		SimpleCollectionWrapper<Type> implements PagedList<Type>, Serializable {
	private static final long serialVersionUID = -5408964230063350352L;
	private PagedSetting pagedSetting = new PagedSettingImpl();

	public PagedListImpl() {
		super();
	}

	public PagedListImpl(int page, int pageSize) {
		super();
		this.setPage(page);
		this.setPageSize(pageSize);
	}

	/**
	 * Set the current page size. Resets the current page number if changed.
	 * <p>
	 * Default value is 10.
	 */
	public void setPageSize(int pageSize) {
		if (pageSize < 1) {
			pageSize = 1;
		}
		if (pageSize != this.pagedSetting.getPageSize()) {
			this.pagedSetting.setPageSize(pageSize);
			this.setPage(1);
		}
	}

	/**
	 * Return the current page size.
	 */
	public int getPageSize() {
		return this.pagedSetting.getPageSize();
	}

	/**
	 * Set the current page number. Page numbering starts with 1.
	 */
	public void setPage(int page) {
		if (page < 1) {
			page = 1;
		}
		if (page != this.pagedSetting.getPage()) {
			this.pagedSetting.setPage(page);
		}
	}

	/**
	 * Return the current page number. Page numbering starts with 1.
	 */
	public int getPage() {
		if (this.pagedSetting.getPage() > getPageCount()) {
			this.setPage(getPageCount());
		}
		return this.pagedSetting.getPage();
	}

	/**
	 * Set the maximum number of page links to a few pages around the current
	 * one.
	 */
	public void setMaxLinkedPages(int maxLinkedPages) {
		this.pagedSetting.setMaxLinkedPages(maxLinkedPages);
	}

	/**
	 * Return the maximum number of page links to a few pages around the current
	 * one.
	 */
	public int getMaxLinkedPages() {
		return this.getMaxLinkedPages();
	}

	/**
	 * Return the number of pages for the current source list.
	 */
	public int getPageCount() {
		float nrOfPages = (float) this.getNrOfElements() / getPageSize();
		return (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1
				: nrOfPages);
	}

	/**
	 * Return if the current page is the first one.
	 */
	public boolean isFirstPage() {
		return getPage() == 1;
	}

	/**
	 * Return if the current page is the last one.
	 */
	public boolean isLastPage() {
		return getPage() == getPageCount();
	}

	/**
	 * Switch to previous page. Will stay on first page if already on first
	 * page.
	 */
	public void previousPage() {
		if (!isFirstPage()) {
			this.setPage(this.getPage() - 1);
		}
	}

	/**
	 * Switch to next page. Will stay on last page if already on last page.
	 */
	public void nextPage() {
		if (!isLastPage()) {
			this.setPage(this.getPage() + 1);
		}
	}

	/**
	 * Return the element index of the first element on the current page.
	 * Element numbering starts with 0.
	 */
	public int getFirstElementOnPage() {
		return PagedSizeUtil.caclStartIndex(getPageSize(), getPage());
	}

	/**
	 * Return the element index of the last element on the current page. Element
	 * numbering starts with 0.
	 */
	public int getLastElementOnPage() {
		return PagedSizeUtil.caclEndIndexByPage(this.getPageSize(), this
				.getPage(), this.getNrOfElements());
	}

	/**
	 * Return the first page to which create a link around the current page.
	 */
	public int getFirstLinkedPage() {
		return Math.max(0, getPage() - (getMaxLinkedPages() / 2));
	}

	/**
	 * Return the last page to which create a link around the current page.
	 */
	public int getLastLinkedPage() {
		return Math.min(getFirstLinkedPage() + getMaxLinkedPages() - 1,
				getPageCount() - 1);
	}

}
